import sys
import importlib.util
from pathlib import Path
from apps.oms.hawkeye.models import Hawkeye, HawkeyeJob
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from django.db import transaction


class CronJobManager:
    def __init__(self):
        self.scheduler = BackgroundScheduler()
        self.scheduler.start()

    def _parse_cron(self, cron_expression: str) -> dict:
        """解析 Cron 表达式为 APScheduler 参数"""
        fields = cron_expression.strip().split()
        field_count = len(fields)

        if field_count not in (5, 6, 7):
            raise ValueError(
                f"Invalid cron format: {cron_expression} (expected 5-7 fields, got {field_count})"
            )

        components = {
            "second": "0" if field_count < 6 else fields[0],
            "minute": fields[0 if field_count < 6 else 1],
            "hour": fields[1 if field_count < 6 else 2],
            "day": fields[2 if field_count < 6 else 3],
            "month": fields[3 if field_count < 6 else 4],
            "day_of_week": fields[4 if field_count < 6 else 5],
            "year": "*" if field_count < 7 else fields[6],
        }

        return components

    def get_job(self, job_id: str):
        return self.scheduler.get_job(job_id)

    def add_job(
        self,
        job_id: str,
        plugin: str,
        hosts: list,
        params: list,
        cron: str,
        dept_belong_id: str,
    ):
        """添加/更新定时任务"""
        parse_cron = self._parse_cron(cron)

        def _execute():
            new_hawkeye_list = []
            dynamic_module = import_module_from_path(plugin)
            hawkeye_messages, hawkeye_job_detail = dynamic_module.main(hosts, params)
            with transaction.atomic():
                for ele in hawkeye_messages:
                    new_message = ele["message"]
                    new_message_obj = Hawkeye.objects.filter(
                        message=new_message
                    ).first()
                    if new_message_obj:
                        break
                    ele["dept_belong_id"] = dept_belong_id
                    new_hawkeye_list.append(Hawkeye(**ele))

                Hawkeye.objects.bulk_create(new_hawkeye_list)
                HawkeyeJob.objects.filter(id=job_id).update(detail=hawkeye_job_detail)

        self.remove_job(job_id)
        self.scheduler.add_job(_execute, trigger=CronTrigger(**parse_cron), id=job_id)

    def remove_job(self, job_id: str):
        """移除指定任务"""
        if self.get_job(job_id):
            self.scheduler.remove_job(job_id)


def import_module_from_path(file_path: str):
    # 转换为 Path 对象处理路径
    script_path = Path(file_path).resolve()  # 确保绝对路径
    if not script_path.exists():
        raise FileNotFoundError(f"脚本不存在: {script_path}")

    # 生成唯一模块名（避免与现有模块冲突）
    module_name = f"dynamic_module_{script_path.stem}"

    # 创建模块规格
    spec = importlib.util.spec_from_file_location(
        name=module_name, location=str(script_path)
    )
    if spec is None:
        raise ImportError(f"无法为 {script_path} 创建模块规格")

    # 创建并加载模块
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module  # 注册到模块系统
    spec.loader.exec_module(module)  # 执行模块代码

    return module
